#ifndef __EMU_H
#define __EMU_H

#include "common.h"
#include "VRena.h"
#include <verilated_vcd_c.h>	// Trace file format header
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/prctl.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef EMU_THREAD
#include <verilated_threads.h>
#endif 
typedef struct shinfo{
  bool flag;
  bool notgood;
  uint64_t endCycles;
} shinfo;

struct EmuArgs {
  uint32_t seed;
  const char *image;
  const char *sd_image;
  const char *mem_image;
  const char *wave_path;
  bool enable_waveform;
  bool enable_jtag;

  EmuArgs() {
    seed = 0;
    wave_path = NULL;
    image = NULL;
    sd_image = NULL;
    mem_image = NULL;
    enable_waveform = true;
    enable_jtag = false;
  }
};

class Emulator {
private:
  VRena *dut_ptr;
  VerilatedVcdC* tfp;
  bool enable_waveform;
  EmuArgs args;

  enum {
    STATE_GOODTRAP = 0,
    STATE_BADTRAP = 1,
    STATE_ABORT = 2,
    STATE_LIMIT_EXCEEDED = 3,
    STATE_SIG = 4,
    STATE_RUNNING = -1
  };

  // emu control variable
  uint64_t cycles;
  int trapCode;

  inline void reset_ncycles(size_t cycles);
  // inline void single_cycle();
  void trigger_stat_dump();
  inline char* timestamp_filename(time_t t, char *buf);
  inline char* waveform_filename(time_t t);
  inline char* cycle_wavefile(uint64_t cycles, time_t t);

public:
Emulator(int argc, const char *argv[]);
  ~Emulator();
  uint64_t execute();
  uint64_t get_cycles() const { return cycles; }
  EmuArgs get_args() const { return args; }
};

#endif
